<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        // 原型：对象创建时所参考的模板，模板创建的对象是无法直接访问的，可以通过__proto__用于指向原型对象的指针属性
        function Student(name){
            this.name=name;
        }
        Student.prototype.say=function(){
            console.log("hello");
        };
        console.log(Student.prototype);
        var stu=new Student("coco");
        console.log(stu.__proto__);
        stu.say();

        // stu---->Student.prototype---->Object.prototype---->null
       /*  原型链：
            因为原型是由构造函数的prototype属性完成数据模板描述，而构造函数本身是一个函数(方法)，
        函数本身是一个具有原型的数据对象，因此当原型指向原型时，如Student中的原型指向Object中的原型，而Object构造函数的原型指向null
        这样的数据的原型的连续的关系称之为原型链 */

        // ES6中提供的标准的方法，去替代__proto__的功能
        // Object.getPrototypeOf(object)  用于获取原型对象
        // Object.setPrototypeOf(object, prototype) 设置原型对象
        // console.log(Object.getPrototypeOf(stu));


       /*  stu.__proto__={

            username:"alice",
            show:function(){
                console.log("嘻嘻");
            }
        }; */

        // 上面的代码等效于下列代码：
        Object.setPrototypeOf(stu,{
            username:"lili",
            show:function(){
                console.log("嘻嘻");
            }
        });
        console.log(stu);
        // console.log(Object.getPrototypeOf(stu));
        // console.log(Object.getPrototypeOf(Object.getPrototypeOf(stu)));
        // stu---->{username:"alice",show:function(){ console.log("嘻嘻");}--->Object.prototype
               
        // ES5中提供的方法
        /*  
            Object.create(prototype, descriptors)
            创建一个新的对象，使用其他对象的原型创建对象 
            prototype提供创建对象时的原型参考
                取值：
                    可以是一个实例(对象)，新建的对象会以该实例(对象)作为原型模板，同时会获取该实例的所有属性
                    可以是一个固定的原型，新建的对象会以该原型作为模板
                    可以是null，创建一个没有原型的特殊对象

            descriptors：取值类型是对象，可以是需要定义的属性名称，value是该属性的相关描述，value的取值是对象(相关的描述符) */
         
        
        var u1=Object.create(stu,{
            name:{
                value:"xixi",
                writable:true,
                configurable:true,
                enumerable:true
            }
        });
        console.log(u1);
        console.log(u1.__proto__);
        // console.log(u1.name);

        // function Person(name){
        //     this.name=name;
        // }
        // var p=new Person("tom");
        // console.log(p);
        // var u2=Object.create(Person.prototype);
        // console.log(u2);
        // // u2 ----> Person.prototype---->Object.prototype---->null

        // var u3=Object.create(null,{
        //     name:{
        //         value:"xixi",
        //         writable:true,
        //         configurable:true,
        //         enumerable:true
        //     },
        //     age:{
        //         configurable:true,
        //         enumerable:true,
        //         get(){  
        //             return "我是返回值"
        //         },
        //         set(val){
        //             console.log("触发了set方法");
        //         }
        //     }
        // });
        // console.log(u3);
        // console.log(Object.getPrototypeOf(u3));
            
            


    </script>
</head>
<body>
    
</body>
</html>